/**
 * 网络请求工具类
 * 封装微信小程序请求API，提供拦截器、队列管理和便捷方法
 */
class wxRequest {
  /**
   * 默认配置参数
   * @property {string} baseUrl - 基础URL前缀
   * @property {string} url - 请求路径
   * @property {object|null} data - 请求数据
   * @property {string} method - 请求方法
   * @property {object} header - 请求头信息
   * @property {number} timeout - 超时时间(毫秒)
   * @property {boolean} isLoading - 是否显示加载提示
   */
  default = {
    baseUrl: '',
    url: '',
    data: null,
    method: 'GET',
    header: {
      'Content-type': 'application/json'
    },
    timeout: 4000,
    isLoading: false
  }

  /**
   * 拦截器对象
   * @property {function} request - 请求拦截器，处理请求前的配置
   * @property {function} response - 响应拦截器，处理响应数据
   */
  interceptors = {
    request: (config) => config,
    response: (response) => response
  }

  /**
   * 请求队列，用于管理loading状态
   */
  queue = []

  /**
   * 构造函数
   * @param {object} params - 自定义默认参数，会与默认配置合并
   */
  constructor(params = {}) {
    this.default = Object.assign({}, this.default, params)
  }

  /**
   * 执行请求方法
   * @param {object} options - 请求配置
   * @returns {Promise} 返回Promise对象
   */
  request(options) {
    // 清除之前的定时器
    this.timer && clearTimeout(this.timer)
    // 组合完整URL
    options.url = this.default.baseUrl + options.url
    // 合并配置
    options = { ...this.default, ...options }
    // 处理加载提示
    if (options.isLoading && options.method !== 'UPLOAD') {
      if (this.queue.length === 0) {
        wx.showLoading({
          title: '加载中',
          mask: true
        })
      }
      this.queue.push('queue')
    }
    // 应用请求拦截器
    options = this.interceptors.request(options)
    // 返回Promise
    return new Promise((resolve, reject) => {
      if (options.method === 'UPLOAD') {
        // 使用微信小程序的上传文件API
        wx.uploadFile({
          ...options, // 传递所有配置参数给上传API
          success: (res) => {
            // 微信上传API返回的数据是字符串格式，需要解析为JSON对象
            res.data = JSON.parse(res.data)
            // 构建标准化的响应对象，包含配置信息和成功标志
            const response = Object.assign({}, res, {
              config: options,
              isSuccess: true
            })
            // 通过拦截器处理响应并返回结果
            resolve(this.interceptors.response(response))
          },
          fail: (err) => {
            // 处理上传失败的情况
            // 构建标准化的错误响应，包含配置信息和失败标志
            const response = Object.assign({}, err, {
              config: options,
              isSuccess: false
            })
            // 通过拦截器处理错误并拒绝Promise
            reject(this.interceptors.response(response))
          }
        })
      } else {
        wx.request({
          ...options,
          success: (res) => {
            // 处理成功响应
            const response = Object.assign({}, res, {
              config: options,
              isSuccess: true
            })
            resolve(this.interceptors.response(response))
          },
          fail: (err) => {
            // 处理失败响应
            const response = Object.assign({}, err, {
              config: options,
              isSuccess: false
            })
            reject(this.interceptors.response(response))
          },
          complete: () => {
            // 处理加载提示关闭逻辑
            if (options.isLoading) {
              this.queue.pop()
              this.queue.length === 0 && this.queue.push('queue')
              this.timer = setTimeout(() => {
                this.queue.pop()
                this.queue.length === 0 && wx.hideLoading()
                clearTimeout(this.timer)
              }, 100)
            }
          }
        })
      }
    })
  }

  /**
   * GET请求方法
   * @param {string} url - 请求路径
   * @param {object} data - 请求参数
   * @param {object} config - 其他配置
   * @returns {Promise} 返回Promise对象
   */
  get(url, data = {}, config = {}) {
    return this.request(
      Object.assign(
        {
          url,
          data,
          method: 'GET'
        },
        config
      )
    )
  }

  /**
   * DELETE请求方法
   * @param {string} url - 请求路径
   * @param {object} data - 请求参数
   * @param {object} config - 其他配置
   * @returns {Promise} 返回Promise对象
   */
  delete(url, data = {}, config = {}) {
    return this.request(
      Object.assign(
        {
          url,
          data,
          method: 'DELETE'
        },
        config
      )
    )
  }

  /**
   * POST请求方法
   * @param {string} url - 请求路径
   * @param {object} data - 请求参数
   * @param {object} config - 其他配置
   * @returns {Promise} 返回Promise对象
   */
  post(url, data = {}, config = {}) {
    return this.request(
      Object.assign(
        {
          url,
          data,
          method: 'POST'
        },
        config
      )
    )
  }

  /**
   * PUT请求方法
   * @param {string} url - 请求路径
   * @param {object} data - 请求参数
   * @param {object} config - 其他配置
   * @returns {Promise} 返回Promise对象
   */
  put(url, data = {}, config = {}) {
    return this.request(
      Object.assign(
        {
          url,
          data,
          method: 'PUT'
        },
        config
      )
    )
  }

  /**
   * 并发请求方法
   * @param {...Promise} promises - 多个Promise请求
   * @returns {Promise} 返回Promise.all结果
   */
  all(...promises) {
    return Promise.all(promises)
  }

  /**
   * 上传文件方法
   * @param {string} url - 请求路径
   * @param {string} filePath - 文件路径
   * @param {string} name - 文件名
   * @param {object} config - 其他配置
   * @returns {Promise} 返回Promise对象
   */
  upload(url, filePath, name = 'file', config = {}) {
    return this.request(
      Object.assign({ url, data: { filePath, name }, method: 'UPLOAD' }, config)
    )
  }
}

export default wxRequest
